package com.pur.zsms.common.dao;

import java.util.List;
import java.util.Map;

import javax.persistence.PersistenceException;

import org.springframework.dao.DataAccessException;

import com.pur.zsms.common.support.JpaLockMode;
import com.pur.zsms.common.support.PageController;

/**
 * <p>定义基本JPA操作的接口，该接口被JpaTemplate实现。该接口通常不直接被使用，
 * 但在测试时，可以方便被mock。</p>
 * <p>对于该类中各个方法的具体细节，可以参考JPA EntityManager的javadoc。</p>
 * <p>Create Time: 2008-10-27</p>
 * @author wangzg002
 *
 */
public interface JpaOperations {
	/**查找指定的entity。 如果这个entity存在于当前的persistence context中，那么返回值是被缓存的对象；否则会创建一个新的entity，并从datastore中加载相关的persistent state。<br>
	 * 如果datastore不存在持有指定persistent identity的记录，那么返回null
	 * @param <T> Class类型
	 * @param entityClass 指定的类
	 * @param id  主键
	 * @return 查找的对象
	 * @throws DataAccessException  数据异常
	 */
	<T> T find(Class<T> entityClass, Object id) throws PersistenceException;

	/**与find相似。不同的是：如果缓存中没有指定的entity，EntityManager会创建一个新的entity.<br>
	 * 不是立即访问数据库（不加载persistent state），而是在第一次访问某个持久字段的时候才加载相应的persistent state
	 * @param <T> Class类型
	 * @param entityClass 指定的类
	 * @param id  主键
	 * @return 查找的对象
	 * @throws PersistenceException  数据异常
	 */
	<T> T getReference(Class<T> entityClass, Object id)
			throws PersistenceException;

	/**当前的persistence context 是否存在该对象
	 * @param entity 对象
	 * @return 是否存在
	 * @throws PersistenceException
	 */
	boolean contains(Object entity) throws PersistenceException;

	/**刷新实体状态<br>
	 * 确保entity的persistent state和数据库中的persistent state同步
	 * @param entity
	 * @throws PersistenceException
	 */
	void refresh(Object entity) throws PersistenceException;

	/**将新创建的entity纳入EntityManager的管理<br>
	 * 在下一次的flush或者commit时，这个entity会被插入到数据库中
	 * @param entity 实体对象
	 * @throws PersistenceException 数据异常
	 */
	void persist(Object entity) throws PersistenceException;

	/**更新实体数据到上下文
	 * @param <T> 实体对象类型
	 * @param entity 实体对象
	 * @return 更新的实体对象
	 * @throws PersistenceException 数据异常
	 */
	<T> T merge(T entity) throws PersistenceException;

	/**删除被管理的entity
	 * @param entity 实体对象
	 * @throws PersistenceException 数据异常
	 */
	void remove(Object entity) throws PersistenceException;

	/**把当前事务中所有的修改写入到数据库中。<br>
	 * 如果EntityManager没有连接到数据库，那么首先会获取一个连接并一直持有到事务结束。<br>
	 * 该方法抛出任何异常都会导致数据回滚.
	 * @throws PersistenceException 访问异常
	 */
	void flush() throws PersistenceException;

	/**清空当前的persistence context内容，被EntityManager管理的所有entities变成detached状态
	 * @throws PersistenceException 访问异常
	 */
	void clear() throws PersistenceException;

	/**通过Java Persistence Query Language (JPQL) string 查询
	 * @param queryString JPQL 查询语句
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List find(String queryString, PageController pageController)
			throws PersistenceException;

	/**包含参数值的JPQL 语句查询(参数按顺序提供)
	 * @param queryString 查询语句
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param values  查询参数数组
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List find(String queryString, PageController pageController,
			Object... values) throws PersistenceException;

	/**使用命名参数的JPQL语句查询
	 * @param queryString 查询语句
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param params Map形式的所有命名参数值
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNamedParams(String queryString, PageController pageController,
			Map<String, ? extends Object> params) throws PersistenceException;

	/**使用命名查询
	 * @param queryName 在Entity中声明的查询名称
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @return 查询结果列表 
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNamedQuery(String queryName, PageController pageController)
			throws PersistenceException;

	/**带有参数值的命名查询
	 * @param queryName 在Entity中声明的查询名称
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param values 参数值数组
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNamedQuery(String queryName, PageController pageController,
			Object... values) throws PersistenceException;

	/**使用命名参数的命名查询
	 * @param queryName 在Entity中声明的查询名称
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param params Map形式的所有命名参数值
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNamedQueryAndNamedParams(String queryName,
			PageController pageController, Map<String, ? extends Object> params)
			throws PersistenceException;

	/**锁定实体对象
	 * @param obj 要锁定的对象
	 * @param lockMode 锁模式
	 * @throws PersistenceException 数据异常
	 */
	void lock(Object obj, JpaLockMode lockMode) throws PersistenceException;

	/**使用标量原生查询<br>
	 * 返回一个查询结果集.<br>
	 * @param sqlString 原生查询语句
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNativeQuery(String sqlString, PageController pageController)
			throws PersistenceException;
	
	/**使用标量原生查询<br>
	 * 返回一个查询结果集.<br>
	 * @param sqlString 原生查询语句
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param values 参数值数组
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNativeQuery(String sqlString,
			final PageController pageController,Object... values) throws PersistenceException;

	/**简单的实体原生查询<br>
	 * 通过一个SQL语句和隐式的映像到一个实体,映射元数据为基础的一个实体.它认为原生查询的结果集中的字段将完全匹配实体的O/R映射
	 * @param sqlString 原生查询语句
	 * @param entityClass 实体类
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNativeQuery(String sqlString, Class entityClass,
			PageController pageController) throws PersistenceException;

	/**简单的实体原生查询<br>
	 * 通过一个SQL语句和隐式的映像到一个实体,映射元数据为基础的一个实体.它认为原生查询的结果集中的字段将完全匹配实体的O/R映射
	 * @param sqlString 原生查询语句
	 * @param entityClass 实体类
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @param values 参数值数组
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNativeQuery(String sqlString, Class entityClass,
			final PageController pageController, Object... values) throws PersistenceException;

	/**简单的实体原生查询
	 * @param sqlString 原生查询语句
	 * @param sqlMapingName 定义的结果映射名称(参见JPA SqlResultSetMapping)
	 * @param pageController 分页控制器(如果不使用分页,置为null即可)
	 * @return 查询结果列表
	 * @throws PersistenceException 数据异常
	 */
	@SuppressWarnings("unchecked")
	List findByNativeQuery(String sqlString, String sqlMapingName,
			PageController pageController) throws PersistenceException;

	//封装对过程方法的调用
	/**无返回值的过程调用(对于Oracle,适用于无参数的PROCEDURE的调用)
	 * @param callString 过程调用语句.格式: "someProcedure()"
	 * @throws PersistenceException
	 */
	void excuteProcedure(String callString) throws PersistenceException;

	/**带参数的无返回值过程调用(对于Oracle,适用于没有OUT参数的PROCEDURE)
	 * @param callString 过程调用语句.格式: "someProcedure(?)"或使用标号"someProcedure(?1,?2)"
	 * @param values 参数值数组
	 * @throws PersistenceException 数据异常
	 */
	void excuteProcedure(String callString, Object... values)
			throws PersistenceException;

	/**返回单值的函数调用(对于Oracle,适用于无参数的FUNCTION的调用)
	 * @param callString 函数调用语句 格式: "someFunction()"
	 * @return 函数调用返回的结果
	 * @throws PersistenceException 数据异常
	 */
	Object callProcedure(String callString) throws PersistenceException;

	/**带参数的返回单值的函数调用(对于Oracle,适用于有参数FUNCTION的调用)
	 * @param callString 函数调用语句.格式: "someFunction(?)"或使用标号"someProcedure(?1,?2)"
	 * @param values 参数值数组
	 * @return 函数调用返回的结果
	 * @throws PersistenceException 数据异常
	 */
	Object callProcedure(String callString, Object... values)
			throws PersistenceException;

	/**执行原生更新操作的方法
	 * @param updateString 批量操作JQL语句
	 * @throws PersistenceException 数据异常
	 */
	int executeNativeUpdate(String updateString) throws PersistenceException;

	/**执行原生更新操作的方法 - 使用标号参数
	 * @param updateString 批量操作JQL语句
	 * @param values 参数值数组
	 * @throws PersistenceException 数据异常
	 */
	int executeNativeUpdate(String updateString, Object... values)
			throws PersistenceException;

	/**执行原生更新操作的方法 - 使用命名参数
	 * @param updateString 批量操作JQL语句
	 * @param params 参数值对
	 * @throws PersistenceException 数据异常
	 */
	int executeNativeUpdate(String updateString, Map<String, ? extends Object> params)
			throws PersistenceException;
	
	/**执行更新操作的方法
	 * @param updateString 批量操作JQL语句
	 * @throws PersistenceException 数据异常
	 */
	int executeUpdate(String updateString) throws PersistenceException;

	/**执行更新操作的方法 - 使用标号参数
	 * @param updateString 批量操作JQL语句
	 * @param values 参数值数组
	 * @throws PersistenceException 数据异常
	 */
	int executeUpdate(String updateString, Object... values)
			throws PersistenceException;

	/**执行更新操作的方法 - 使用命名参数
	 * @param updateString 批量操作JQL语句
	 * @param params 参数值对
	 * @throws PersistenceException 数据异常
	 */
	int executeUpdate(String updateString, Map<String, ? extends Object> params)
			throws PersistenceException;
}
